﻿import json
import os
import time
import traceback

import requests
import simplejson
from django.conf import settings
from django.http.response import HttpResponse, HttpResponseBadRequest
from django.views.decorators.csrf import csrf_exempt
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.views import APIView
from rest_framework.viewsets import ViewSet
from rest_framework.response import Response
from rest_framework.decorators import action
from rest_framework import status, viewsets, filters
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.authentication import BasicAuthentication, SessionAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication

from account.admin import User
from account.serializers import FetchAccountUserSerializer
from celery_tasks.sms.tasks import send_print_file
from common import DINGTALK_BASE_URL
from common.token_check import ApiPermissionCheck
from common.utils import SendMsg, filter_field_list
from config.settings.base import logger
from service.models import Cc
from service.serializers import LoonFlowAttachmentSerializer, CcSerializer
from common.upload import uploadfile
from apps.apirequest import WorkFlowAPiRequest


class LoonFlowAPIView(APIView):
    authentication_classes = [JSONWebTokenAuthentication, SessionAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request, format='json'):
        #resp = requests.get('http://localhost:6060/api/v1.0/workflows').text

        #resp = simplejson.loads(resp)
        ins = WorkFlowAPiRequest(username=self.request.user.username)
        rstatus, resp = ins.getdata(self.request.query_params, method='get', url='/api/v1.0/workflows')
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'], 'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response({'code': resp['code'], 'data': None, 'msg': resp['msg']}, status=status_resp)


class LoonFlowInitStateViewSet(ViewSet):
    authentication_classes = [JSONWebTokenAuthentication, SessionAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def retrieve(self, request, pk=None):
        username = request.user.username
        #resp = requests.get('http://localhost:6060/api/v1.0/workflows/{}/init_state?username={}'.format(pk, username)).text
        #resp = simplejson.loads(resp)
        ins = WorkFlowAPiRequest(username=self.request.user.username)
        rstatus, resp = ins.getdata(self.request.query_params, method='get', url='/api/v1.0/workflows/{}/init_state?username={}'.format(pk, username))
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'], 'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response({'code': resp['code'], 'data': None, 'msg': resp['msg']}, status=status_resp)


class LoonFlowCreateTicketViewSet(ViewSet):
    authentication_classes = [JSONWebTokenAuthentication, SessionAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def create(self, request):
        request.data['username'] = request.user.username
        #resp = requests.post('http://localhost:6060/api/v1.0/tickets', data=simplejson.dumps(request.data)).text
        #resp = simplejson.loads(resp)
        ins = WorkFlowAPiRequest(username=self.request.user.username)
        rstatus, resp = ins.getdata(self.request.query_params, method='post', url='/api/v1.0/tickets', data=request.data)
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'], 'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response({'code': resp['code'], 'data': None, 'msg': resp['msg']}, status=status_resp)


class LoonFlowTicketViewSet(ViewSet):
    authentication_classes = [JSONWebTokenAuthentication, SessionAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def list(self, request, format='json'):
        username = request.user.username
        category = request.query_params.get('category', None)
        cc = request.query_params.get('cc', None)
        if cc:
            if cc == "all":
                cc_list = list(Cc.objects.filter(username=username).values_list('ticket_id', flat=True))
            if cc == "unread":
                cc_list = list(Cc.objects.filter(username=username, is_read=False).values_list('ticket_id', flat=True))
            ticket_ids = ','.join(map(lambda x: str(x), cc_list))
            if not cc_list:
                ticket_ids = '0'
            url = '/api/v1.0/tickets?username={}&ticket_ids={}'.format(username, ticket_ids)
        else:
            url = '/api/v1.0/tickets?username={}'.format(username)
        page = request.query_params.get('page', 1)
        ins = WorkFlowAPiRequest(username=self.request.user.username)
        rstatus, resp = ins.getdata(self.request.query_params, method='get', url=url)
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'], 'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response({'code': resp['code'], 'data': None, 'msg': resp['msg']}, status=status_resp)

    def retrieve(self, request, pk=None):
        username = request.user.username
        #resp = requests.get('http://localhost:6060/api/v1.0/tickets/{}?username={}'.format(pk, username)).text
        #resp = simplejson.loads(resp)
        ins = WorkFlowAPiRequest(username=self.request.user.username)
        rstatus, resp = ins.getdata(self.request.query_params, method='get', url='/api/v1.0/tickets/{}?username={}'.format(pk, username))
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            if 'field_list' in resp['data'].get('value', ''):
                resp['data']['value']['field_list'] = filter_field_list(resp['data']['value']['field_list'])
            return Response({'code': resp['code'], 'data': resp['data'], 'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response({'code': resp['code'], 'data': None, 'msg': resp['msg']}, status=status_resp)

    def partial_update(self, request, pk=None):
        request.data['username'] = request.user.username
        #resp = requests.patch('http://localhost:6060/api/v1.0/tickets/{}'.format(pk), data=simplejson.dumps(request.data)).text
        # print(resp)
        #resp = simplejson.loads(resp)
        ins = WorkFlowAPiRequest(username=self.request.user.username)
        rstatus, resp = ins.getdata(parameters=self.request.query_params, method='patch', url='/api/v1.0/tickets/{}'.format(pk), data=request.data)
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'], 'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response({'code': resp['code'], 'data': None, 'msg': resp['msg']}, status=status_resp)

    @action(methods=['post'], detail=True)
    def accept(self, request, pk=None):
        """
        接单
        """
        username = request.user.username
        ins = WorkFlowAPiRequest(username=request.user.username)
        rstatus, resp = ins.getdata(request.query_params, method='post',
                                    url='/api/v1.0/tickets/{}/accept?username={}'.format(
                                        pk, username),
                                    data=request.data)
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'],
                             'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response(
                {'code': resp['code'], 'data': None, 'msg': resp['msg']},
                status=status_resp)

    @action(methods=['post'], detail=True)
    def deliver(self, request, pk=None):
        """
        转交
        """
        username = request.user.username
        ins = WorkFlowAPiRequest(username=request.user.username)
        rstatus, resp = ins.getdata(request.query_params, method='post',
                                    url='/api/v1.0/tickets/{}/deliver?username={}'.format(
                                        pk, username),
                                    data=request.data)
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'],
                             'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response(
                {'code': resp['code'], 'data': None, 'msg': resp['msg']},
                status=status_resp)

    @action(methods=['post'], detail=True)
    def add_node(self, request, pk=None):
        """
        加签
        """
        username = request.user.username
        ins = WorkFlowAPiRequest(username=request.user.username)
        rstatus, resp = ins.getdata(request.query_params, method='post',
                                    url='/api/v1.0/tickets/{}/add_node?username={}'.format(
                                        pk, username),
                                    data=request.data)
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'],
                             'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response(
                {'code': resp['code'], 'data': None, 'msg': resp['msg']},
                status=status_resp)

    @action(methods=['post'], detail=True)
    def add_node_end(self, request, pk=None):
        """
        加签处理完成
        """
        username = request.user.username
        ins = WorkFlowAPiRequest(username=request.user.username)
        rstatus, resp = ins.getdata(request.query_params, method='post',
                                    url='/api/v1.0/tickets/{}/add_node_end?username={}'.format(
                                        pk, username),
                                    data=request.data)
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'],
                             'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response(
                {'code': resp['code'], 'data': None, 'msg': resp['msg']},
                status=status_resp)

    @action(methods=['post'], detail=True)
    def close(self, request, pk=None):
        """
        强制关闭工单
        """
        username = request.user.username
        ins = WorkFlowAPiRequest(username=request.user.username)
        rstatus, resp = ins.getdata(request.query_params, method='post',
                                    url='/api/v1.0/tickets/{}/close?username={}'.format(
                                        pk, username),
                                    data=request.data)
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'],
                             'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response(
                {'code': resp['code'], 'data': None, 'msg': resp['msg']},
                status=status_resp)

    @action(methods=['post'], detail=True)
    def retreat(self, request, pk=None):
        """
        撤回工单
        """
        username = request.user.username
        ins = WorkFlowAPiRequest(username=request.user.username)
        rstatus, resp = ins.getdata(request.query_params, method='post',
                                    url='/api/v1.0/tickets/{}/retreat?username={}'.format(
                                        pk, username),
                                    data=request.data)
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'],
                             'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response(
                {'code': resp['code'], 'data': None, 'msg': resp['msg']},
                status=status_resp)

    @action(methods=['post'], detail=False)
    def to_print(self, request, pk=None):
        """
        打印工单
        """
        try:
            media_url = request.data.get('media_url')
            assert media_url, "The media_id parameter is required"
            username = request.user.username
            if settings.DEBUG:
                SendMsg.send_print(username, media_url)
            else:
                send_print_file.delay(username, media_url)
            status_resp = status.HTTP_200_OK
            msg = 'ok'
        except Exception:
            status_resp = status.HTTP_400_BAD_REQUEST
            msg = '发送打印文件失败！'
        return Response({'msg': msg}, status=status_resp)


class LoonFlowStepViewSet(ViewSet):
    authentication_classes = [JSONWebTokenAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def retrieve(self, request, pk=None):
        username = request.user.username
        #resp = requests.get('http://localhost:6060/api/v1.0/tickets/{}/flowsteps?username={}'.format(pk, username)).text
        #resp = simplejson.loads(resp)
        ins = WorkFlowAPiRequest(username=self.request.user.username)
        rstatus, resp = ins.getdata(self.request.query_params, method='get', url='/api/v1.0/tickets/{}/flowsteps?username={}'.format(pk, username))

        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'], 'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response({'code': resp['code'], 'data': None, 'msg': resp['msg']}, status=status_resp)


class LoonFlowTransitionViewSet(ViewSet):
    authentication_classes = [JSONWebTokenAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def retrieve(self, request, pk=None):
        username = request.user.username
        #resp = requests.get('http://localhost:6060/api/v1.0/tickets/{}/flowlogs?username={}'.format(pk, username)).text
        #resp = simplejson.loads(resp)
        ins = WorkFlowAPiRequest(username=self.request.user.username)
        rstatus, resp = ins.getdata(self.request.query_params, method='get', url='/api/v1.0/tickets/{}/flowlogs?username={}'.format(pk, username))
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'], 'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response({'code': resp['code'], 'data': None, 'msg': resp['msg']}, status=status_resp)


class LoonFlowTranActionViewSet(ViewSet):
    authentication_classes = [JSONWebTokenAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def retrieve(self, request, pk=None):
        username = request.user.username
        #resp = requests.get('http://localhost:6060/api/v1.0/tickets/{}/transitions?username={}'.format(pk, username)).text
        #resp = simplejson.loads(resp)
        ins = WorkFlowAPiRequest(username=self.request.user.username)
        rstatus, resp = ins.getdata(self.request.query_params, method='get', url='/api/v1.0/tickets/{}/transitions?username={}'.format(pk, username))
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'], 'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response({'code': resp['code'], 'data': None, 'msg': resp['msg']}, status=status_resp)


class LoonFlowStateViewSet(ViewSet):
    authentication_classes = [JSONWebTokenAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def retrieve(self, request, pk=None):
        #resp = requests.get('http://localhost:6060/api/v1.0/workflows/{}/states?username={}'.format(pk, username)).text
        #resp = simplejson.loads(resp)
        ins = WorkFlowAPiRequest(username=self.request.user.username)
        rstatus, resp = ins.getdata(self.request.query_params, method='get', url='/api/v1.0/workflows/{}/states'.format(pk))
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            return Response({'code': resp['code'], 'data': resp['data'], 'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response({'code': resp['code'], 'data': None, 'msg': resp['msg']}, status=status_resp)


class LoonFlowCommentsViewSet(ViewSet):
    """
    新增工单评论/注释
    """
    authentication_classes = [JSONWebTokenAuthentication, SessionAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def create(self, request):
        username = request.user.username
        ins = WorkFlowAPiRequest(username=request.user.username)
        ticket_id = request.data.pop('ticket_id')
        rstatus, resp = ins.getdata(request.query_params, method='post', url='/api/v1.0/tickets/{}/comments?username={}'.format(
                                    ticket_id, username),
                                    data=request.data)
        if resp['code'] == 0:
            status_resp = status.HTTP_200_OK
            suggestion = json.loads(request.data.get("suggestion"))
            if suggestion.get("users") and suggestion.get("type") == 'comment':
                user_list = suggestion.get("users")
                textarea_value = suggestion.get("textarea_value")
                ticket_creator = suggestion.get("ticketCreator")
                workflow_name = suggestion.get("workflow_name")
                comment_creator = suggestion.get("commentCreator")
                for user in user_list:
                    username = user["username"]
                    SendMsg.send_at_msg(username, ticket_id, textarea_value, ticket_creator, workflow_name, comment_creator)

            return Response({'code': resp['code'], 'data': resp['data'], 'msg': resp['msg']},
                            status=status_resp)
        else:
            status_resp = status.HTTP_400_BAD_REQUEST
            return Response({'code': resp['code'], 'data': None, 'msg': resp['msg']}, status=status_resp)


@csrf_exempt
def ueditor_index(request):
    action = request.GET.get('action', '')
    if action == 'config':
        setting = settings.UEDITER_SETTING
        return HttpResponse(simplejson.dumps(setting), content_type='text/html; charset=utf-8')
    elif action == 'uploadfile':
        return HttpResponse(ueditor_uploadfile(request))
    elif action == 'uploadimage':
        return HttpResponse(ueditor_uploadimage(request))
    else:
        return HttpResponseBadRequest()


def format_file_name(name):
    '''
    去掉名称中的url关键字
    '''
    URL_KEY_WORDS = ['#', '?', '/', '&', '.', '%']
    for key in URL_KEY_WORDS:
        name_list = name.split(key)
        name = ''.join(name_list)
    return name


def upload_file(file_obj, file_type='pic'):
    if file_obj:
        filename = file_obj.name
        # filename = file_obj.name.decode('utf-8', 'ignore')
        filename_list = filename.split('.')
        file_postfix = filename_list[-1]  # 后缀
        # if file_postfix in ['txt', 'sql']:
        filename_list_clean = filename_list[:-1]
        file_name = ''.join(filename_list_clean) + str(int(time.time() * 1000))
        file_name = format_file_name(file_name)
        # else:
        #     file_name = str(uuid.uuid1())
        sub_folder = time.strftime("%Y%m")
        upload_folder = os.path.join(settings.MEDIA_ROOT, 'upload', sub_folder)
        if not os.path.exists(upload_folder):
            os.makedirs(upload_folder)
        absolute_path = os.path.join(upload_folder, file_name) + '.%s' % file_postfix
        if file_postfix.lower() in (
            "sql", "jpg", "jpeg", "bmp", "gif", "png", "xls", "xlsx", "rar", "doc", "docx", "zip", "pdf", "txt", "swf",
                "wmv"):
            destination = open(absolute_path, 'wb+')
            for chunk in file_obj.chunks():
                destination.write(chunk)
            destination.close()

            # if file_type == 'pic':  #暂不剪切图片
            #     if file_postfix.lower() in ('jpg', 'jpeg', 'bmp', 'gif', 'png'):
            #         im = Image.open(absolute_path)
            #         im.thumbnail((720, 720))
            #         im.save(absolute_path)

            real_url = os.path.join('/media/', 'upload', sub_folder, file_name) + '.%s' % file_postfix
            response_dict = {'original': filename, 'url': real_url, 'title': 'source_file_tile', 'state': 'SUCCESS',
                             'msg': ''}
        else:
            response_dict = {'original': filename, 'url': '', 'title': 'source_file_tile', 'state': 'FAIL',
                             'msg': 'invalid file format'}
    else:
        response_dict = {'original': '', 'url': '', 'title': 'source_file_tile', 'state': 'FAIL',
                         'msg': 'invalid file obj'}
    return simplejson.dumps(response_dict)


@csrf_exempt
def ueditor_uploadimage(request):
    """
    上传图片
    :param request:
    :return:
    """
    fileObj = request.FILES.get('upfile', None)
    response = upload_file(fileObj, 'pic')
    return HttpResponse(response)


@csrf_exempt
def ueditor_uploadfile(request):
    """ 上传文件 """
    fileObj = request.FILES.get('upfile', None)
    response = upload_file(fileObj, 'file')
    return HttpResponse(response)


class CcViewSet(viewsets.ModelViewSet):
    """
    抄送列表
    """
    filter_backends = (DjangoFilterBackend, filters.SearchFilter,)
    filter_fields = ('username', )
    search_fields = ('username', )
    pagination_class = None
    queryset = Cc.objects.all()
    serializer_class = CcSerializer
    permission_classes = [IsAuthenticated, ]

    def get_permissions(self):
        if self.action in ['bulck_cc', 'send_msg']:
            self.permission_classes = [ApiPermissionCheck, ]
        return [permission() for permission in self.permission_classes]

    def perform_create(self, serializer):
        cc = serializer.save()
        SendMsg.send_cc(cc)

    @action(methods=['post'], detail=False)
    def bulck_cc(self, request, pk=None):
        """
        创建多条抄送记录
        hook调用此api返回的数据如下：
            {
                "id": 11,
                "sn": "loonflow202002020001",
                "title": "xxx",
                "state_id": 1,
                 ...., //等等工单的所有字段的值
                "extra_info": [{"type": "person", "to": ["240345616626300820", "223703516326313962"]}]
            }
        """
        data = {}
        data_list = request.data.get('extra_info')
        ticket_id = request.data.get('id')
        workflow_id = request.data.get("workflow_id")
        try:
            user_info_list = []
            for info in data_list:
                if info["type"] == "person":
                    for user in info['to']:
                        cc = Cc()
                        cc.username = user
                        user_info = FetchAccountUserSerializer(User.objects.filter(username=user).first()).data
                        user_info_list.append(user_info)
                        cc.ticket_id = ticket_id
                        cc.save()
                        SendMsg.send_cc(cc, workflow_id)
                else:
                    pass  # 抄送对象是机构或角色
            data_info = {
                "users": user_info_list,
                "type": "cc"
            }

            data['code'] = 0
            data['msg'] = json.dumps(data_info)
        except:
            logger.error(traceback.format_exc())
            data['code'] = -1
            data['msg'] = '抄送失败'
        return Response(data=data)

    @action(methods=['post'], detail=False)
    def cc_read(self, request, pk=None):
        """
        抄送已读
        """
        data = {}
        username = request.user.username
        ticket_id = request.data.get('ticket_id')
        ins = WorkFlowAPiRequest(username=request.user.username)
        try:
            cc_qs = Cc.objects.filter(ticket_id=ticket_id, username=username, is_read=False)
            if cc_qs.exists():
                cc_qs.update(is_read=True)
                rstatus, resp = ins.getdata(method='post',
                                            url='/api/v1.0/tickets/{}/comments?username={}'.format(
                                                ticket_id, username),
                                            data={"suggestion": json.dumps({"type": "read"})})
                if resp['code'] == 0:
                    logger.info("已读评论成功")
                else:
                    logger.error("已读评论失败")

            data['result'] = 'info'
            data['msg'] = '已读'
        except:
            logger.error(traceback.format_exc())
            data['result'] = 'error'
            data['msg'] = '已读失败'
        return Response(data=data)
